package br.ufc.apsoo.controllers;

import static br.com.caelum.vraptor.view.Results.json;

import java.util.Date;
import java.util.List;

import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.caelum.vraptor.view.Results;
import br.ufc.apsoo.models.Apartamento;
import br.ufc.apsoo.models.Despesa;
import br.ufc.apsoo.models.Reserva;
import br.ufc.apsoo.models.Servico;
import br.ufc.apsoo.repositories.TodasDespesas;
import br.ufc.apsoo.repositories.TodasReservas;
import br.ufc.apsoo.repositories.TodosApartamentos;
import br.ufc.apsoo.repositories.TodosServicos;

@Resource
public class DespesaController {

	private final Result result;
	private final Validator validator;

	private final TodasDespesas todasDespesas;

	private final TodosApartamentos todosApartamentos;

	private final TodosServicos todosServicos;

	private final TodasReservas todasReservas;

	public DespesaController(Result result, Validator validator,
			TodasDespesas todasDespesas, TodosApartamentos todosApartamentos,
			TodosServicos todosServicos, TodasReservas todasReservas) {
		this.result = result;
		this.validator = validator;
		this.todasDespesas = todasDespesas;
		this.todosApartamentos = todosApartamentos;
		this.todosServicos = todosServicos;
		this.todasReservas = todasReservas;
	}

	@Delete
	@Path("/despesa/estornar/{despesa.id}")
	public void estornar(Despesa despesa) {
		todasDespesas.estornar(despesa);
		result.use(Results.status()).ok();
	}

	@Get
	@Path("/despesa")
	public void index() {
		List<Apartamento> apartamentos = todosApartamentos.ocupados();
		List<Servico> servicos = todosServicos.ativos();

		if (!result.included().containsKey("despesa")) {
			Despesa despesa = new Despesa();
			despesa.setData(new Date());
			result.include("despesa", despesa);
		}
		result.include("apartamentos", apartamentos);
		result.include("servicos", servicos);
	}

	@Post
	@Path("/despesa/lancar")
	public void lancar(Despesa despesa) {
		validaDespesa(despesa);
		validator.onErrorRedirectTo(this).index();
		if (!validator.hasErrors()) {
			Reserva reserva = todasReservas.ocupandoApartamento(despesa
					.getReserva().getApartamento());
			despesa.setReserva(reserva);
			todasDespesas.lancar(despesa);
		}
		result.include("despesa", despesa);
		result.redirectTo(this).index();
	}

	@Get
	@Path("/despesa/lista/{apartamento.numero}")
	public void listaPorApartamento(Apartamento apartamento) {
		apartamento = todosApartamentos.trazPorNumero(apartamento.getNumero());
		if (apartamento != null) {
			List<Despesa> despesas = todasDespesas.doApartamento(apartamento);
			result.use(json()).withoutRoot().from(despesas)
					.include("servico").serialize();
			result.use(Results.status()).ok();
		} else {
			result.use(Results.status()).notFound();
		}
	}

	private void validaDespesa(Despesa despesa) {
		validator.validate(despesa);
		if (despesa.getReserva().getApartamento().getNumero().equals(0)) {
			validator.add(new ValidationMessage("Selecione um apartamento!",
					"erro"));
		}

		if (despesa.getServico().getId().equals(new Long(0))) {
			validator
					.add(new ValidationMessage("Selecione um serviço!", "erro"));
		}
	}
}
